package danran.dbapi.plugin.internal;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import danran.dbapi.common.ApiConfig;
import danran.dbapi.plugin.CachePlugin;
import danran.dbapi.plugin.PluginConf;
import danran.dbapi.plugin.log.Logger;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.util.Map;

/**
 * @Classname RedisCachePlugin
 * @Description TODO
 * @Date 2022/2/8 12:05
 * @Created by RanCoder
 */
public class RedisCachePlugin extends CachePlugin {
    private static final Logger log = Logger.getInstance(RedisCachePlugin.class);
    private JedisPool pool;

    /**
     * 插件初始化方法，实例化插件的时候执行，永远只会执行一次，
     * 一般是用来创建连接池
     */
    @Override
    public void init() {
        JedisPoolConfig jcon = new JedisPoolConfig();

        int maxTotal = PluginConf.getKey("RedisMaxTotal") == null ? 200 : Integer.parseInt(PluginConf.getKey("RedisMaxTotal"));
        int maxIdle = PluginConf.getKey("RedisMaxIdle") == null ? 50 : Integer.parseInt(PluginConf.getKey("RedisMaxIdle"));
        String ip = PluginConf.getKey("RedisCachePlugin.ip");
        int port = Integer.parseInt(PluginConf.getKey("RedisCachePlugin.port"));
        String password = PluginConf.getKey("RedisCachePlugin.password");
        int redis_db = Integer.parseInt(PluginConf.getKey("RedisCachePlugin.db"));

        jcon.setMaxTotal(maxTotal);
        jcon.setMaxIdle(maxIdle);
        jcon.setTestOnBorrow(true);
        jcon.setTestOnReturn(true);
        if (!"".equals(password)) {
            this.pool = new JedisPool(jcon, ip, port, 100, password, redis_db);
        } else {
            this.pool = new JedisPool(jcon, ip, port, 100, null, redis_db);
        }
        log.info("init jedis pool success");
    }

    /**
     * 缓存设置
     *
     * @param config        api配置
     * @param requestParams request参数
     * @param data          要缓存的数据
     */
    @Override
    public void set(ApiConfig config, Map<String, Object> requestParams, Object data) {
        String expireTime = config.getCachePluginParams();
        log.info("Start to add data to the cache.");
        try (Jedis jedis = pool.getResource()) {
//            String key = "api-" + config.getId();
//            // 构建Hash的hashkey
//            StringBuilder subKeyBuilder = new StringBuilder();
//            for (Object param : requestParams.values()) {
//                subKeyBuilder.append(param.toString()).append("-");
//            }
//            String subKey = subKeyBuilder.toString();

//            jedis.hset(key, subKey, JSON.toJSONString(data));
            HashKey keys = generateKey(config, requestParams);
            jedis.hset(keys.key, keys.fieldKey, JSON.toJSONString(data));
            // 设置过期时间
            if (!"".equals(expireTime)) {
                jedis.expire(keys.key, Integer.parseInt(expireTime));
            }
        } catch (Exception e) {
            log.info(e.toString());
            e.printStackTrace();
        }
        log.info("Successfully add data to the cache.");
    }

    /**
     * 清除所有缓存，API修改、删除、下线的时候会触发清除缓存
     *
     * @param config api配置
     */
    @Override
    public void clean(ApiConfig config) {
        try (Jedis jedis = pool.getResource()) {
            jedis.del("api-" + config.getId());
        } catch (Exception e) {
            log.info(e.toString());
            e.printStackTrace();
        }
    }

    /**
     * 查询缓存
     *
     * @param config        api配置
     * @param requestParams request参数
     * @return
     */
    @Override
    public Object get(ApiConfig config, Map<String, Object> requestParams) {
        log.info("Try to get data from cache.");
        try (Jedis jedis = pool.getResource()) {
            HashKey keys = generateKey(config, requestParams);
            String res = jedis.hget(keys.key, keys.fieldKey);
            return JSON.parseArray(res, JSONObject.class);
        } catch (Exception e) {
            log.info(e.toString());
            e.printStackTrace();
        }
        return null;
    }

    private HashKey generateKey(ApiConfig config, Map<String, Object> requestParams) {
        String key = "api-" + config.getId();
        // 构建Hash的hashkey
        StringBuilder subKeyBuilder = new StringBuilder();
        for (Object param : requestParams.values()) {
            subKeyBuilder.append(param.toString()).append("-");
        }
        String subKey = subKeyBuilder.toString();
        return new HashKey(key, subKey);
    }

    static class HashKey {
        String key;
        String fieldKey;

        public HashKey(String key, String fieldKey) {
            this.key = key;
            this.fieldKey = fieldKey;
        }
    }

}
